﻿using System.Linq;
using System.Windows.Controls;
using System.Windows.Forms;
using DirectXMetaData;
using HlslCompiler;
using SlimDX.D3DCompiler;
using UserControl = System.Windows.Controls.UserControl;

namespace EffectEd
{
    /// <summary>
    /// Interaction logic for CompilerSettings.xaml
    /// </summary>
    public partial class CompilerSettingsControl : UserControl
    {

        private CodeAssistance _codeAssistance;

        public CompilerSettingsControl()
        {
            InitializeComponent();
        }

        public void Initialize(CodeAssistance codeAssistance)
        {
            _codeAssistance = codeAssistance;
            comboBox1.DisplayMemberPath = "Version";
            comboBox1.SelectedValuePath = "Version";
            comboBox1.ItemsSource = _codeAssistance.Versions;
        }

        public void SetCompilerSettings(CompilerSettings settings)
        {
            comboBox1.SelectedValue = settings.Direct3D;
            comboBox2.SelectedValue = settings.Profile;
            textBox1.Text = settings.EntryPoint;
            checkBoxAvoidFlowControl.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.AvoidFlowControl);
            checkBoxDebug.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.Debug);
            checkBoxEnableBackwardsCompatibility.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.EnableBackwardsCompatibility);
            checkBoxEnableIEEEStrictness.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.EnableIEEEStrictness);
            checkBoxEnableStrictness.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.EnableStrictness);
            checkBoxForceSoftwarePixelShader.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.ForceSoftwarePixelShader);
            checkBoxForceSoftwareVertexShader.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.ForceSoftwareVertexShader);
            checkBoxNoPreshader.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.NoPreshader);
            checkBoxOptimizationLevel0.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.OptimizationLevel0);
            //checkBoxOptimizationLevel1.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.OptimizationLevel1);
            checkBoxOptimizationLevel2.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.OptimizationLevel2);
            checkBoxOptimizationLevel3.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.OptimizationLevel3);
            checkBoxPackMatrixColumnMajor.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.PackMatrixColumnMajor);
            checkBoxPackMatrixRowMajor.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.PackMatrixRowMajor);
            checkBoxPartialPrecision.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.PartialPrecision);
            checkBoxPreferFlowControl.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.PreferFlowControl);
            checkBoxSkipOptimization.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.SkipOptimization);
            checkBoxSkipValidation.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.SkipValidation);
            checkBoxWarningsAreErrors.IsChecked = settings.ShaderFlags.HasFlag(ShaderFlags.WarningsAreErrors);

            checkBoxAllowSlowOperations.IsChecked = settings.EffectFlags.HasFlag(EffectFlags.AllowSlowOperations);
            checkBoxChildEffect.IsChecked = settings.EffectFlags.HasFlag(EffectFlags.ChildEffect);
            checkBoxSingleThreaded.IsChecked = settings.EffectFlags.HasFlag(EffectFlags.SingleThreaded);
        }

        public CompilerSettings GetCompilerSettings()
        {
            var settings = new CompilerSettings();
            settings.Direct3D = (comboBox1.SelectedItem as DirectX).Version;
            settings.Profile = (comboBox2.SelectedItem as Profile).Name;
            settings.EntryPoint = textBox1.Text;

            settings.ShaderFlags = ShaderFlags.None;
            if (checkBoxAvoidFlowControl.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.AvoidFlowControl;
            if (checkBoxDebug.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.Debug;
            if (checkBoxEnableBackwardsCompatibility.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.EnableBackwardsCompatibility;
            if (checkBoxEnableIEEEStrictness.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.EnableIEEEStrictness;
            if (checkBoxEnableStrictness.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.EnableStrictness;
            if (checkBoxForceSoftwarePixelShader.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.ForceSoftwarePixelShader;
            if (checkBoxForceSoftwareVertexShader.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.ForceSoftwareVertexShader;
            if (checkBoxNoPreshader.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.NoPreshader;
            if (checkBoxOptimizationLevel0.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.OptimizationLevel0;
            //if (checkBoxOptimizationLevel1.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.OptimizationLevel1;
            if (checkBoxOptimizationLevel2.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.OptimizationLevel2;
            if (checkBoxOptimizationLevel3.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.OptimizationLevel3;
            if (checkBoxPackMatrixColumnMajor.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.PackMatrixColumnMajor;
            if (checkBoxPackMatrixRowMajor.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.PackMatrixRowMajor;
            if (checkBoxPartialPrecision.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.PartialPrecision;
            if (checkBoxPreferFlowControl.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.PreferFlowControl;
            if (checkBoxSkipOptimization.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.SkipOptimization;
            if (checkBoxSkipValidation.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.SkipValidation;
            if (checkBoxWarningsAreErrors.IsChecked.Value) settings.ShaderFlags |= ShaderFlags.WarningsAreErrors;

            settings.EffectFlags = EffectFlags.None;
            if (checkBoxAllowSlowOperations.IsChecked.Value) settings.EffectFlags |= EffectFlags.AllowSlowOperations;
            if (checkBoxChildEffect.IsChecked.Value) settings.EffectFlags |= EffectFlags.ChildEffect;
            if (checkBoxSingleThreaded.IsChecked.Value) settings.EffectFlags |= EffectFlags.SingleThreaded;

            return settings;
        }

        private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            comboBox2.DisplayMemberPath = "Name";
            comboBox2.SelectedValuePath = "Name";
            comboBox2.ItemsSource = _codeAssistance.Versions.Single(v => v.Version == ((DirectX)comboBox1.SelectedItem).Version).CompileProfiles.OrderBy(p => p.Name);
            comboBox2.SelectedIndex = 0;
        }

        private void checkBoxAvoidFlowControl_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            SetCompilerSettings(GetCompilerSettings()); // refresh using the binary value so the repercussions of one flag in others is visualized.
        }

    }
}
